Skip to main content

4: Create Connection

Now that the Issuer has a credential definition, they can start issuing credentials. However, in order to do that, they first needs to create a connection to the holder. There are multiple ways to create connections. We will use the /v1/connections/ endpoints in these examples.

Create connection between Issuer and Holder

As the Issuer we create a connection invitation.

Note: The multi_use field indicates that the invitation url can be accepted by multiple tenants to create connections with them. use_public_did can be set to true for issuers making the invitation, because they are onboarded with a public did, but it's not necessary. It will simply allow the holder to validate the did of the issuer, as they will then be able to see it in the connection record.

curl -X 'POST' \
'https://cloudapi.test.didxtech.com/tenant/v1/connections/create-invitation' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-H 'x-api-key: tenant.<Issuer token>' \
-d '{
"alias": "Issuer <> Holder",
"multi_use": false,
"use_public_did": false
}'

Response:

{
"connection_id": "c78f9423-370e-4800-a48e-962456083943",
"invitation": {
"@id": "6a86e6c7-af25-4e5d-87fe-b42f559b13b9",
"@type": "https://didcomm.org/connections/1.0/invitation",
"did": null,
"imageUrl": "https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png",
"label": "Demo Issuer",
"recipientKeys": ["91ZNSpDgVoV12kHcmUqyp1JmGeKE7oGi9NFd2WMzKt4X"],
"routingKeys": null,
"serviceEndpoint": "http://governance-multitenant-agent:3020"
},
"invitation_url": "http://governance-multitenant-agent:3020?c_i=eyJAdHlwZSI6ICJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMC9pbnZpdGF0aW9uIiwgIkBpZCI6ICI2YTg2ZTZjNy1hZjI1LTRlNWQtODdmZS1iNDJmNTU5YjEzYjkiLCAic2VydmljZUVuZHBvaW50IjogImh0dHA6Ly9nb3Zlcm5hbmNlLW11bHRpdGVuYW50LWFnZW50OjMwMjAiLCAiaW1hZ2VVcmwiOiAiaHR0cHM6Ly91cGxvYWQud2lraW1lZGlhLm9yZy93aWtpcGVkaWEvY29tbW9ucy83LzcwL0V4YW1wbGUucG5nIiwgInJlY2lwaWVudEtleXMiOiBbIjkxWk5TcERnVm9WMTJrSGNtVXF5cDFKbUdlS0U3b0dpOU5GZDJXTXpLdDRYIl0sICJsYWJlbCI6ICJEZW1vIElzc3VlciJ9"
}

The Holder accepts the connection by using the invitation object above, and by posting to the /v1/connections/accept-invitation endpoint.

Note: the invitation object can also be obtained by decoding the base64 payload in the invitation_url, after the c_i= indicator.

curl -X 'POST' \
'https://cloudapi.test.didxtech.com/tenant/v1/connections/accept-invitation' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-H 'x-api-key: tenant.<Holder token>' \
-d '{
"alias": "Holder <> Issuer",
"use_existing_connection": false,
"invitation": {
"@id": "6a86e6c7-af25-4e5d-87fe-b42f559b13b9",
"@type": "https://didcomm.org/connections/1.0/invitation",
"did": null,
"imageUrl": "https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png",
"label": "Demo Issuer",
"recipientKeys": [
"91ZNSpDgVoV12kHcmUqyp1JmGeKE7oGi9NFd2WMzKt4X"
],
"routingKeys": null,
"serviceEndpoint": "http://governance-multitenant-agent:3020"
}
}'

Response:

{
"alias": "Holder <> Issuer",
"connection_id": "ac3b0d56-eb33-408a-baeb-0370164d47ae",
"connection_protocol": "connections/1.0",
"created_at": "2023-11-20T09:56:41.437966Z",
"error_msg": null,
"invitation_key": "91ZNSpDgVoV12kHcmUqyp1JmGeKE7oGi9NFd2WMzKt4X",
"invitation_mode": "once",
"invitation_msg_id": "6a86e6c7-af25-4e5d-87fe-b42f559b13b9",
"my_did": "MYhLew4uq58mou8SCTNFYp",
"state": "request-sent",
"their_did": null,
"their_label": "Demo Issuer",
"their_public_did": null,
"their_role": "inviter",
"updated_at": "2023-11-20T09:56:41.472385Z"
}

Both of the tenants can listen to Webhook/SSE events to track the progress of the connection being made. Once the state is completed, the connection is made. This can also be asserted by fetching connection records for the holder or issuer, and validating that their connection has transitioned to state: completed.

Below is an example of a webhook event indicating the completed state.

NOTE: The field IDs will be unique to each tenant i.e. the connection_id of the Issuer will be different from that of the Holder, even though they refer to the same connection.

{
"wallet_id": "4e0c70fb-f2ad-4f59-81f3-93d8df9b977a",
"topic": "connections",
"origin": "multitenant",
"payload": {
"alias": "Holder <> Issuer",
"connection_id": "359b30a2-c98d-4c00-b318-8185d1d0e64d",
"connection_protocol": "connections/1.0",
"created_at": "2023-11-16T07:57:18.451554Z",
"error_msg": null,
"invitation_key": "8Vd5YSVBw5p6BJ8nHngZ2UcCKBmTSxQHoNWfaBQJXW5U",
"invitation_mode": "once",
"invitation_msg_id": "0ef82415-20ba-4d1e-818b-92a70355ec6e",
"my_did": "NXk4JkDpFff4MpnTwvn1Wa",
"state": "completed",
"their_did": "LN2WMyrMFH74L1GTkSteka",
"their_label": "Demo Issuer",
"their_public_did": null,
"their_role": "inviter",
"updated_at": "2023-11-16T07:57:18.748560Z"
}
}

Next: 5: Issue a Credential